package com.sale.goods.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sale.common.core.constant.CacheNames;
import com.sale.common.core.exception.GlobalException;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.mybatis.core.page.PageQuery;
import com.sale.common.mybatis.core.page.TableDataInfo;
import com.sale.common.redis.utils.CacheUtils;
import com.sale.common.satoken.utils.LoginHelper;
import com.sale.goods.api.dto.ImparityGoodsDto;
import com.sale.goods.api.vo.GetDataByCodeGoodsVo;
import com.sale.goods.domain.*;
import com.sale.goods.domain.dto.GoodsDisburseDto;
import com.sale.goods.domain.dto.ReceiptAndPaymentDocDto;
import com.sale.goods.domain.dto.single.GoodsDisburseSingle;
import com.sale.goods.domain.vo.GoodsDisburseVo;
import com.sale.goods.mapper.GoodsCalculateMapper;
import com.sale.goods.mapper.GoodsDisburseMapper;
import com.sale.goods.mapper.GoodsOtherMapper;
import com.sale.goods.service.IGoodsDisburseService;
import com.sale.order.api.RemoteSupplierService;
import com.sale.system.api.RemoteAccountManagementService;
import com.sale.system.api.RemoteCodeService;
import com.sale.system.api.RemoteReviewService;
import com.sale.system.api.RemoteStaffManagementService;
import com.sale.system.api.domain.SysBalance;
import com.sale.system.api.domain.SysDictData;
import com.sale.system.api.domain.vo.SysAuditHistoryVo;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 其他支出单
 * @Param
 * @Date 23-08-08
 * @Author hl
 **/
@RequiredArgsConstructor
@Service
public class GoodsDisburseServiceImpl implements IGoodsDisburseService {

    private final GoodsDisburseMapper goodsDisburseMapper;

    private final GoodsOtherMapper goodsOtherMapper;

    private final GoodsCalculateMapper goodsCalculateMapper;

    @DubboReference
    private final RemoteReviewService remoteReviewService;

    @DubboReference
    private final RemoteCodeService remoteCodeService;

    @DubboReference
    private final RemoteSupplierService remoteSupplierService;

    @DubboReference
    private final RemoteStaffManagementService remoteStaffManagementService;

    @DubboReference
    private final RemoteAccountManagementService remoteAccountManagementService;


    /**
     * 查询其他收入单
     *
     * @param goodSDisburseVo,pageQuery
     * @return 其他收入单
     */
    @Override
    public TableDataInfo<GoodsDisburseDto> selectDisburseList(GoodsDisburseVo goodSDisburseVo, PageQuery pageQuery) {
        Page<GoodsDisburseDto> page = goodsDisburseMapper.selectDisburseList(pageQuery.build(), this.buildQueryWrapper(goodSDisburseVo));
        List<SysDictData> netArray = CacheUtils.get(CacheNames.SYS_DICT, "bill_state");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //供应商
        Map<String,String> supplierMap= remoteSupplierService.getOpenSupplierFinance();
        //职员
        Map<String, String> map = remoteStaffManagementService.selectAllStaffManagement();
        List<GoodsDisburseDto> list = page.getRecords();
        for (GoodsDisburseDto dto:
            list) {
            dto. setDisburseStatusDict(netMap.get(dto.getDisburseStatus()));
            dto.setSupplierName(supplierMap.get(dto.getSupplierCode()));
            dto.setDisburseBy(map.get(dto.getDisburseBy()));
        }
        return TableDataInfo.build(page);
    }

    private Wrapper<GoodsDisburseVo> buildQueryWrapper(GoodsDisburseVo goodsDisburseVo) {
        QueryWrapper<GoodsDisburseVo> wrapper = Wrappers.query();

        String name = goodsDisburseVo.getDisburseBy();
        if(StringUtils.isNotBlank(name)){
            Long staffId = remoteStaffManagementService.selectStaffManagementName(name);
            goodsDisburseVo.setDisburseBy(String.valueOf(staffId));
        }
        String name2 = goodsDisburseVo.getSupplierName();
        if(StringUtils.isNotBlank(name2)){
            String code = remoteSupplierService.getCodeBySupplierName(name2);
            goodsDisburseVo.setSupplierName(code);
        }
        wrapper
            .like(ObjectUtil.isNotNull(goodsDisburseVo.getDisburseCode()), "disburse_code", goodsDisburseVo.getDisburseCode())
            .eq(StringUtils.isNotBlank(goodsDisburseVo.getSupplierCode()), "supplier_code", goodsDisburseVo.getSupplierCode())
            .like(StringUtils.isNotBlank(goodsDisburseVo.getDisburseBy()), "disburse_by", goodsDisburseVo.getDisburseBy())
            .like(StringUtils.isNotBlank(goodsDisburseVo.getSupplierName()), "supplier_code", goodsDisburseVo.getSupplierName())
            .eq(StringUtils.isNotBlank(goodsDisburseVo.getDisburseStatus()), "disburse_status", goodsDisburseVo.getDisburseStatus())
            .eq(StringUtils.isNotBlank(goodsDisburseVo.getCollectionStatus()), "collection_status", goodsDisburseVo.getCollectionStatus()).between(goodsDisburseVo.getBeginTime() != null && goodsDisburseVo.getEndTime() != null,
                "create_time", goodsDisburseVo.getBeginTime(), goodsDisburseVo.getEndTime());
        return wrapper;
    }

    /**
     * 新增其他收入单
     *
     * @param goodsDisburseVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDisburse(GoodsDisburseVo goodsDisburseVo) throws Exception {
        GoodsDisburse disburse = new GoodsDisburse();
        BeanUtils.copyProperties(goodsDisburseVo, disburse);
        Long id = IdWorker.getId();
        disburse.setDisburseId(id);
        //新增明细(账户)
        List<GoodsOther> list = goodsDisburseVo.getOtherList();
        //收款金额
        BigDecimal b1 = new BigDecimal(0);
        for (GoodsOther goodsOther :
            list) {
            b1 = b1.add(goodsOther.getOtherAmount());
            goodsOther.setRelevanceId(id);
        }
        disburse.setDisburseAmount(b1);
        //新增账号明细
        goodsOtherMapper.insertBatch(list);
        //新增主列表
        //本次收款
        BigDecimal amount = disburse.getReceivedAmount();
        if(amount.signum()>0){
            //金额
            BigDecimal amount3 = b1.subtract(amount);
            if(amount3.signum()>0){
                disburse.setCollectionStatus(3);
            }else {
                disburse.setCollectionStatus(2);
            }
        }else{
            disburse.setCollectionStatus(1);
        }
        String authorityCoding = remoteCodeService.authorityCoding("finance:expenditure:list");
        if (authorityCoding == null) {
            throw new GlobalException("未进行单据配置,单据编码生成失败");
        }
        if (goodsDisburseVo.getCollectionAccount() == 9999) {
            List<GoodsCalculate> list2 = goodsDisburseVo.getCalculateList();
            //新增账号明细
            list2.stream().forEach(goodsCalculate -> goodsCalculate.setRelevanceId(id));
            goodsCalculateMapper.insertBatch(list2);
        }
        disburse.setDisburseCode(authorityCoding);
        disburse.setDisburseStatus(1);
        int os = goodsDisburseMapper.insert(disburse);
        return os;
    }

    /**
     * 查询单个其他收入单
     *
     * @param disburseId
     * @return int
     */
    @Override
    public GoodsDisburseSingle selectDisburseById(long disburseId) {
        GoodsDisburse disburse = goodsDisburseMapper.selectById(disburseId);
        GoodsDisburseSingle single = new GoodsDisburseSingle();
        BeanUtils.copyProperties(disburse, single);
        Map<String, Object> map = new HashMap<>();
        map.put("relevance_id", disburseId);
        if (single.getCollectionAccount() == 9999) {
            List<GoodsCalculate> list2 = goodsCalculateMapper.selectByMap(map);
            single.setCalculateList(list2);
        }
        List<GoodsOther> otherList = goodsOtherMapper.selectByMap(map);
        single.setOtherList(otherList);
        return single;
    }

    /**
     * 删除单个收款单
     *
     * @param disburseId
     * @return int
     */
    @Override
    public int deleteDisburseById(Long disburseId) {
        GoodsDisburse goodsDisburse = goodsDisburseMapper.selectById(disburseId);
        //删除多账户数据
        Map<String, Object> map = new HashMap<>();
        map.put("relevance_id", disburseId);
        if (goodsDisburse.getCollectionAccount() == 9999) {
            //删除账号明细
            goodsCalculateMapper.deleteByMap(map);
        }
        int os = goodsDisburseMapper.deleteById(disburseId);
        //删除明细数据
        goodsOtherMapper.deleteByMap(map);
        return os;
    }

    /**
     * 修改收款单
     *
     * @param goodsDisburseVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDisburseEdit(GoodsDisburseVo goodsDisburseVo) {
        if(goodsDisburseVo.getDisburseStatus().equals("4")){
            SysAuditHistoryVo vo = new SysAuditHistoryVo();
            vo.setPerms("finance:expenditure:examine");
            vo.setAuditDoc(goodsDisburseVo.getDisburseCode());
            int is = remoteReviewService.editHistory(vo);
            if (is == 0) {
                throw new GlobalException("修改失败,未找到审核历史!");
            }
        }
        GoodsDisburse coll = new GoodsDisburse();
        BeanUtils.copyProperties(goodsDisburseVo, coll);
        Long id = coll.getDisburseId();
        //删除明细数据
        Map<String, Object> map = new HashMap<>();
        map.put("relevance_id", id);
        goodsOtherMapper.deleteByMap(map);
        if (goodsDisburseVo.getCollectionAccount() == 9999) {
            List<GoodsCalculate> list2 = goodsDisburseVo.getCalculateList();
            list2.stream().forEach(goodsCalculate -> goodsCalculate.setRelevanceId(id));
            goodsCalculateMapper.insertBatch(list2);
        }
        //新增明细(账户)
        List<GoodsOther> list = goodsDisburseVo.getOtherList();
        //收款金额
        BigDecimal b1 = new BigDecimal(0);
        for (GoodsOther goodsOther :
            list) {
            b1 = b1.add(goodsOther.getOtherAmount());
            goodsOther.setRelevanceId(id);
        }
        coll.setDisburseAmount(b1);
        //新增账号明细
        goodsOtherMapper.insertBatch(list);
        //新增主列表
        //本次收款
        BigDecimal amount = coll.getReceivedAmount();
        if(amount.signum()>0){
            //金额
            BigDecimal amount3 = b1.subtract(amount);
            if(amount3.signum()>0){
                coll.setCollectionStatus(3);
            }else {
                coll.setCollectionStatus(2);
            }
        }else{
            coll.setCollectionStatus(1);
        }
        coll.setDisburseStatus(1);
        int os = goodsDisburseMapper.updateById(coll);
        return os;
    }


    /**
     * 提交审核
     *
     * @param DisburseId
     * @return int
     */
    @Override
    public int submitReview(Long DisburseId) {
        GoodsDisburse coll = goodsDisburseMapper.selectById(DisburseId);
        int status = coll.getDisburseStatus();
        if (status != 1) {
            throw new GlobalException("只有待提交状态才能进行提交审核");
        }
        GoodsDisburse coll2 = new GoodsDisburse();
        coll2.setDisburseId(DisburseId);
        coll2.setDisburseStatus(2);
        return goodsDisburseMapper.updateById(coll2);
    }

    /**
     * 撤销审核
     *
     * @param DisburseId
     * @return int
     */
    @Override
    public int deleteReview(Long DisburseId) {
        GoodsDisburse coll = goodsDisburseMapper.selectById(DisburseId);
        int status = coll.getDisburseStatus();
        if (status != 2) {
            throw new GlobalException("只有待审核状态才能进行撤销审核");
        }
        GoodsDisburse coll2 = new GoodsDisburse();
        coll2.setDisburseId(DisburseId);
        coll2.setDisburseStatus(1);
        return goodsDisburseMapper.updateById(coll2);
    }

    /**
     * 审核单据
     *
     * @param goodsDisburseVo
     * @return int
     */
    @Override
    public int goodSExamineReview(GoodsDisburseVo goodsDisburseVo) throws Exception {
        SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
        Long id = goodsDisburseVo.getDisburseId();
        GoodsDisburse coll = goodsDisburseMapper.selectById(id);
        String perms = "finance:expenditure:examine";
        sysAuditHistoryVo.setPerms(perms);
        sysAuditHistoryVo.setModuleType(3);
        sysAuditHistoryVo.setAuditState(goodsDisburseVo.getAuditState());
        sysAuditHistoryVo.setAuditRemarks(goodsDisburseVo.getAuditOpinion());
        sysAuditHistoryVo.setAuditDoc(coll.getDisburseCode());
        sysAuditHistoryVo.setUserId(LoginHelper.getUserId());
        int data = remoteReviewService.getSequence(sysAuditHistoryVo);
        if (data == 0) {
            throw new GlobalException("未对该审核进行配置");
        }
        //1:通过，2：审核中，3：没权限 4:该人已经审核过
        GoodsDisburse goods = new GoodsDisburse();
        goods.setDisburseId(id);
        switch (data) {
            case 1:
                if(goodsDisburseVo.getAuditState()==2){
                    goods.setDisburseStatus(4);
                }else{
                    goods.setDisburseStatus(5);
                }
                break;
            case 2:
                goods.setDisburseStatus(3);
                break;
            case 3:
                if (data == 0) {
                    throw new GlobalException("不具备审核权限");
                }
                break;
            case 4:
                if (data == 0) {
                    throw new GlobalException("请勿重复审核");
                }
                break;
        }
        //【已收金额】回传到【账户管理】里的对应账户
        if(goodsDisburseVo.getAuditState()==1){
            //需要判断是否是多账户
            if(coll.getCollectionAccount()==9999){
                List<SysBalance> list1 = new ArrayList<>();
                Map<String, Object> map = new HashMap<>();
                map.put("relevance_id", id);
                List<GoodsCalculate>  calculateList = goodsCalculateMapper.selectByMap(map);
                for (GoodsCalculate calculate:
                    calculateList) {
                    SysBalance sys = new SysBalance();
                    sys.setAccountsId(Long.parseLong(calculate.getCalculateAccount()));
                    sys.setBalance(calculate.getAmountReceived());
                    list1.add(sys);
                }
                int j = remoteAccountManagementService.editListBalance2(list1);
                if (j == 0) {
                    throw new GlobalException("未回传余额,请重试");
                }
            }else{
                SysBalance sys = new SysBalance();
                sys.setBalance(coll.getReceivedAmount());
                sys.setAccountsId(coll.getCollectionAccount());
                int i = remoteAccountManagementService.editBalance2(sys);
                if (i == 0) {
                    throw new GlobalException("未回传余额,请重试");
                }
            }
        }
        //审核人
        goods.setExamineBy(LoginHelper.getUsername());
        //审核日期
        goods.setExamineTime(new Date());
        return goodsDisburseMapper.updateById(goods);

    }


    /**
     * 获取其他支出单 (弹框)
     */
    @Override
    public TableDataInfo<ReceiptAndPaymentDocDto> selectDisbursePopList(GoodsDisburseVo goodsDisburseVo, PageQuery pageQuery) {
        Page<ReceiptAndPaymentDocDto> page = goodsDisburseMapper.selectDisbursePopList(pageQuery.build(), this.buildQueryWrapper(goodsDisburseVo));
        return TableDataInfo.build(page);
    }

    /**
     * 财务-核销单 通过获取未全部核销的其他支出单数据
     */
    @Override
    public List<ImparityGoodsDto> getNoVerificationList(GetDataByCodeGoodsVo getDataByCodeVo) {
        return goodsDisburseMapper.getNoVerificationList(getDataByCodeVo);
    }
}
